<?php

namespace App\Http\Middleware;

use App\Exceptions\BadException;
use App\Services\Permission\AdminService;
use App\Services\Permission\MenuService;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
use Illuminate\Support\Facades\Route;
use App\Helpers\Jwt;
use App\Jobs\LogRequest;

class VerifyToken
{
    /**
     * 白名单路由
     *
     * @var array
     */
    protected $whiteList = [
        'login',          // 登录接口
        'logout',         // 注销接口
    ];

    /**
     * Authorization token 检验中间件
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function handle(Request $request, Closure $next): Response
    {
        // 当前路由名称
        $routeName = Route::current()->getName();

        // 检查当前路由是否在白名单中
        if (in_array($routeName, $this->whiteList)) {
            return $next($request);
        }

        // 获取 Authorization 头中的 token
        $token = $request->header('Authorization');

        // 检查 token 是否存在
        if (is_null($token)) {
            throw new BadException('token不存在，请登录！', Response::HTTP_UNAUTHORIZED);
        }

        // 清理 token 字符串
        $token = trim(str_replace('Bearer', '', $token));

        // 检查 token 格式是否正确
        if (count(explode('.', $token)) !== 3) {
            throw new BadException('非法身份信息,禁止登录', Response::HTTP_FORBIDDEN);
        }

        // 验证 token
        try {
            $claims = Jwt::getInstance()->validateToken($token);
        } catch (\Exception $e) {
            throw new BadException('无效的 token', Response::HTTP_UNAUTHORIZED);
        }

        // 将 admin_id 添加到请求中
        $request->merge(['admin_id' => $claims['admin_id']]);

        // 验证权限
        $adminService = app(AdminService::class);
        $rules = $adminService->getCodes($claims['admin_id']);

        // 检查当前路由名称是否在权限列表中
        if (!in_array($routeName, $rules) && $claims['admin_id'] !== 1) {
            throw new BadException('你没有此权限', Response::HTTP_FORBIDDEN);
        }

        // 获取菜单标题
        $menuService = app(MenuService::class);
        $menu = $menuService->findByConditions(['perms' => $routeName], [], ['name'], true);
        $title = $menu ? $menu->toArray()['name'] : '未知操作';

        // 准备日志数据
        $logData = [
            'admin_id'   => $claims['admin_id'],
            'admin_name' => $claims['username'],
            'title'      => $title,
            'url'        => $request->path(),
            'ip'         => $request->ip(),
            'browser'    => $request->header('User-Agent'),
            'method'     => $request->method(),
            'params'     => json_encode($request->all()),
            'created_at' => now(),
        ];

        // 派发队列任务
        dispatch(new LogRequest($logData));

        // 继续处理请求
        return $next($request);
    }
}